home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / updates / update21.zoo / libg++ / src / iostream.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-03  |  16.0 KB  |  763 lines

  1. //    This is part of the iostream library, providing input/output for C++.
  2. //    Copyright (C) 1991 Per Bothner.
  3. //
  4. //    This library is free software; you can redistribute it and/or
  5. //    modify it under the terms of the GNU Library General Public
  6. //    License as published by the Free Software Foundation; either
  7. //    version 2 of the License, or (at your option) any later version.
  8. //
  9. //    This library is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. //    Library General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU Library General Public
  15. //    License along with this library; if not, write to the Free
  16. //    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #ifdef __GNUG__
  19. #pragma implementation
  20. #endif
  21. #define _STREAM_COMPAT
  22. #include <ioprivat.h>
  23. #include <iostream.h>
  24. #include <stdio.h>  /* Needed for sprintf */
  25. #include <ctype.h>
  26. #include <floatio.h>
  27.  
  28. #define    BUF        (MAXEXP+MAXFRACT+1)    /* + decimal point */
  29.  
  30. //#define isspace(ch) ((ch)==' ' || (ch)=='\t' || (ch)=='\n')
  31.  
  32. extern backupbuf not_open_filebuf;
  33.  
  34. istream::istream() : ios(¬_open_filebuf)
  35. {
  36.     _flags |= ios::dont_close;
  37.     _gcount = 0;
  38.     _tie = NULL;
  39. }
  40.  
  41. istream::istream(streambuf *sb, ostream* tied) : ios(sb)
  42. {
  43.     _flags |= ios::dont_close;
  44.     _gcount = 0;
  45.     _tie = tied;
  46. }
  47.  
  48. istream::~istream()
  49. {
  50.     if (!(_flags & (unsigned int)ios::dont_close))
  51.     delete _strbuf;
  52.     _flags |= ios::dont_close;
  53.     _strbuf = ¬_open_filebuf;
  54. }
  55.  
  56. int skip_ws(streambuf* sb)
  57. {
  58.     int ch;
  59.     for (;;) {
  60.     ch = sb->sbumpc();
  61.     if (ch == EOF || !isspace(ch))
  62.         return ch;
  63.     }
  64. }
  65.  
  66. istream& istream::get(char& c)
  67. {
  68.     if (ipfx1()) {
  69.     int ch = _strbuf->sbumpc();
  70.     if (ch == EOF) set(ios::eofbit|ios::failbit);
  71.     else c = (char)ch;
  72.     }
  73.     return *this;
  74. }
  75.  
  76. istream& istream::ignore(int n=1, int delim = EOF)
  77. {
  78.     if (ipfx1()) {
  79.     register streambuf* sb = _strbuf;
  80.     if (delim == EOF) {
  81.         _gcount = sb->ignore(n);
  82.         return *this;
  83.     }
  84.     _gcount = 0;
  85.     for (;;) {
  86. #if 0
  87.         if (n != MAXINT) // FIXME
  88. #endif
  89.         if (--n < 0)
  90.         break;
  91.         int ch = sb->sbumpc();
  92.         if (ch == EOF) {
  93.         set(ios::eofbit|ios::failbit);
  94.         break;
  95.         }
  96.         _gcount++;
  97.         if (ch == delim)
  98.         break;
  99.     }
  100.     }
  101.     return *this;
  102. }
  103.  
  104. istream& istream::read(char *s, size_t n)
  105. {
  106.     if (ipfx1()) {
  107.     if (_strbuf->sgetn(s, n) != n)
  108.         set(ios::failbit);
  109.     }
  110.     return *this;
  111. }
  112.  
  113. istream& istream::seekg(streampos pos)
  114. {
  115.     pos = _strbuf->seekpos(pos, ios::in);
  116.     if (pos == streampos(EOF))
  117.     set(ios::badbit);
  118.     return *this;
  119. }
  120.  
  121. istream& istream::seekg(streamoff off, _seek_dir dir)
  122. {
  123.     streampos pos = _strbuf->seekoff(off, dir, ios::in);
  124.     if (pos == streampos(EOF))
  125.     set(ios::badbit);
  126.     return *this;
  127. }
  128.  
  129. streampos istream::tellg()
  130. {
  131.     streampos pos = _strbuf->seekoff(0, ios::cur, ios::in);
  132.     if (pos == streampos(EOF))
  133.     set(ios::badbit);
  134.     return pos;
  135. }
  136.  
  137. istream& istream::scan(const char *format ...)
  138. {
  139.     if (ipfx0()) {
  140.     va_list ap;
  141.     va_start(ap, format);
  142.     _strbuf->vscan(format, ap);
  143.     va_end(ap);
  144.     }
  145.     return *this;
  146. }
  147.  
  148. istream& istream::vscan(const char *format, _G_va_list args)
  149. {
  150.     if (ipfx0())
  151.     _strbuf->vscan(format, args);
  152.     return *this;
  153. }
  154.  
  155. istream& operator>>(istream& is, char& c)
  156. {
  157.     if (is.ipfx0()) {
  158.     int ch = is._strbuf->sbumpc();
  159.     if (ch == EOF)
  160.         is.set(ios::eofbit|ios::failbit);
  161.     else
  162.         c = (char)ch;
  163.     }
  164.     return is;
  165. }
  166.  
  167. istream& operator>>(istream& is, char* ptr)
  168. {
  169.     if (is.ipfx0()) {
  170.     register streambuf* sb = is._strbuf;
  171.     int ch = sb->sbumpc();
  172.     if (ch == EOF)
  173.         is.set(ios::eofbit|ios::failbit);
  174.     else {
  175.         int w = is.width(0);
  176.         *ptr++ = ch;
  177.         for (;;) {
  178.         ch = sb->sbumpc();
  179.         if (ch == EOF) {
  180.             is.set(ios::eofbit|ios::failbit);
  181.             break;
  182.         }
  183.         else if (isspace(ch)) {
  184.             sb->sputbackc(ch);
  185.             break;
  186.         }
  187.         else if (w == 1) {
  188.             is.set(ios::failbit);
  189.             sb->sputbackc(ch);
  190.             break;
  191.         }
  192.         else *ptr++ = ch;
  193.         w--;
  194.         }
  195.     }
  196.     }
  197.     *ptr = '\0';
  198.     return is;
  199. }
  200.  
  201. static int read_int(istream& stream, unsigned long& val, int& neg)
  202. {
  203.     if (!stream.ipfx0())
  204.     return 0;
  205.     register streambuf* sb = stream.rdbuf();
  206.     int base = 10;
  207.     int ndigits = 0;
  208.     register int ch = skip_ws(sb);
  209.     if (ch == EOF)
  210.     goto eof_fail;
  211.     neg = 0;
  212.     if (ch == '+') {
  213.     ch = skip_ws(sb);
  214.     }
  215.     else if (ch == '-') {
  216.     neg = 1;
  217.     ch = skip_ws(sb);
  218.     }
  219.     if (ch == EOF) goto eof_fail;
  220.     if (!(stream.flags() & (ios::hex|ios::dec|ios::oct))) {
  221.     if (ch == '0') {
  222.         ch = sb->sbumpc();
  223.         if (ch == EOF) {
  224.         val = 0;
  225.         return 1;
  226.         }
  227.         if (ch == 'x' || ch == 'X') {
  228.         base = 16;
  229.         ch = sb->sbumpc();
  230.         if (ch == EOF) goto eof_fail;
  231.         }
  232.         else {
  233.         sb->sputbackc(ch);
  234.         base = 8;
  235.         ch = '0';
  236.         }
  237.     }
  238.     }
  239.     else if (stream.flags() & ios::hex)
  240.     base = 16;
  241.     else if (stream.flags() & ios::oct)
  242.     base = 8;
  243.     val = 0;
  244.     for (;;) {
  245.     if (ch == EOF)
  246.         break;
  247.     int digit;
  248.     if (ch >= '0' && ch <= '9')
  249.         digit = ch - '0';
  250.     else if (ch >= 'A' && ch <= 'F')
  251.         digit = ch - 'A' + 10;
  252.     else if (ch >= 'a' && ch <= 'f')
  253.         digit = ch - 'a' + 10;
  254.     else
  255.         digit = 999;
  256.     if (digit >= base)
  257.         if (ndigits == 0)
  258.         goto fail;
  259.         else {
  260.         sb->sputbackc(ch);
  261.         return 1;
  262.         }
  263.     ndigits++;
  264.     val = base * val + digit;
  265.     ch = sb->sbumpc();
  266.     }
  267.     return 1;
  268.   fail:
  269.     stream.set(ios::failbit);
  270.     return 0;
  271.   eof_fail:
  272.     stream.set(ios::failbit|ios::eofbit);
  273.     return 0;
  274. }
  275.  
  276. #define READ_INT(TYPE) \
  277. istream& operator>>(istream& is, TYPE& i)\
  278. {\
  279.     unsigned long val; int neg;\
  280.     if (read_int(is, val, neg)) {\
  281.     if (neg) val = -val;\
  282.     i = (TYPE)val;\
  283.     }\
  284.     return is;\
  285. }
  286.  
  287. READ_INT(short)
  288. READ_INT(unsigned short)
  289. READ_INT(int)
  290. READ_INT(unsigned int)
  291. READ_INT(long)
  292. READ_INT(unsigned long)
  293.  
  294. istream& operator>>(istream& is, double& x)
  295. {
  296.     if (is.ipfx0()) {
  297.     is.scan("%lg", &x);
  298.     }
  299.     return is;
  300. }
  301. istream& operator>>(istream& is, float& x)
  302. {
  303.     if (is.ipfx0()) {
  304.     is.scan("%g", &x);
  305.     }
  306.     return is;
  307. }
  308.  
  309. istream& operator>>(istream& is, register streambuf* sbuf)
  310. {
  311.     if (is.ipfx0()) {
  312.     register streambuf* inbuf = is.rdbuf();
  313.     // FIXME: Should optimize!
  314.     for (;;) {
  315.         register int ch = inbuf->sbumpc();
  316.         if (ch == EOF) {
  317.         is.set(ios::eofbit);
  318.         break;
  319.         }
  320.         if (sbuf->sputc(ch) == EOF) {
  321.         is.set(ios::failbit);
  322.         break;
  323.         }
  324.     }
  325.     }
  326.     return is;
  327. }
  328.  
  329. ostream& operator<<(ostream& os, char c)
  330. {
  331.     if (os.opfx()) {
  332.     int w = os.width(0);
  333.     char fill_char = os.fill();
  334.     register int padding = w > 0 ? w - 1 : 0;
  335.     register streambuf *sb = os._strbuf;
  336.     if (!(os.flags() & ios::left)) // Default adjustment.
  337.         while (--padding >= 0) sb->sputc(fill_char);
  338.     sb->sputc(c);
  339.     if (os.flags() & ios::left) // Left adjustment.
  340.         while (--padding >= 0) sb->sputc(fill_char);
  341.     os.osfx();
  342.     }
  343.     return os;
  344. }
  345.  
  346. void write_int(ostream& stream, unsigned long val, int neg)
  347. {
  348.     char buf[10 + sizeof(unsigned long) * 3];
  349.     char *show_base = "";
  350.     int show_base_len = 0;
  351.     if ((stream.flags() & (ios::oct|ios::hex)) == 0) // Decimal
  352.     sprintf(buf, "%lu", val);
  353.     else if (stream.flags() & ios::oct) { // Oct
  354.     sprintf(buf, "%lo", val);
  355.     if (stream.flags() & ios::showbase)
  356.         show_base = "0", show_base_len = 1;
  357.     }
  358.     else if (stream.flags() & ios::uppercase) {// Hex
  359.     sprintf(buf, "%lX", val);
  360.     if (stream.flags() & ios::showbase)
  361.         show_base = "0X", show_base_len = 2;
  362.     }
  363.     else { // Hex
  364.     sprintf(buf, "%lx", val);
  365.     if (stream.flags() & ios::showbase)
  366.         show_base = "0x", show_base_len = 2;
  367.     }
  368.     int buf_len = strlen(buf);
  369.     int w = stream.width(0);
  370.     int show_pos = 0;
  371.     int i;
  372.  
  373.     // Calculate padding.
  374.     int len = buf_len;
  375.     if (neg) len++;
  376.     else if (val != 0 && (stream.flags() & ios::showpos)) len++, show_pos=1;
  377.     len += show_base_len;
  378.     int padding = len > w ? 0 : w - len;
  379.  
  380.     // Do actual output.
  381.     register streambuf* sbuf = stream.rdbuf();
  382.     unsigned long pad_kind =
  383.     stream.flags() & (ios::left|ios::right|ios::internal);
  384.     char fill_char = stream.fill();
  385.     if (pad_kind != (unsigned long)ios::left // Default (right) adjustment.
  386.     && pad_kind != (unsigned long)ios::internal)
  387.     for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  388.     if (neg) sbuf->sputc('-');
  389.     else if (show_pos) sbuf->sputc('+');
  390.     if (show_base_len)
  391.     sbuf->sputn(show_base, show_base_len);
  392.     if (pad_kind == (unsigned long)ios::internal)
  393.     for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  394.     sbuf->sputn(buf, buf_len);
  395.     if (pad_kind == (unsigned long)ios::left) // Left adjustment.
  396.     for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  397.     stream.osfx();
  398. }
  399.  
  400. ostream& operator<<(ostream& os, int n)
  401. {
  402.     if (os.opfx()) {
  403.     int neg = 0;
  404.     if (n < 0 && (os.flags() & (ios::oct|ios::hex)) == 0)
  405.         n = -n, neg = 1;
  406.     write_int(os, n, neg);
  407.     }
  408.     return os;
  409. }
  410.  
  411. ostream& operator<<(ostream& os, long n)
  412. {
  413.     if (os.opfx()) {
  414.     int neg = 0;
  415.     if (n < 0 && (os.flags() & (ios::oct|ios::hex)) == 0)
  416.         n = -n, neg = 1;
  417.     write_int(os, n, neg);
  418.     }
  419.     return os;
  420. }
  421.  
  422. ostream& operator<<(ostream& os, unsigned int n)
  423. {
  424.     if (os.opfx())
  425.     write_int(os, n, 0);
  426.     return os;
  427. }
  428.  
  429. ostream& operator<<(ostream& os, unsigned long n)
  430. {
  431.     if (os.opfx())
  432.     write_int(os, n, 0);
  433.     return os;
  434. }
  435.  
  436. ostream& operator<<(ostream& os, float n)
  437. {
  438.     return os << (double)n;
  439. }
  440.  
  441. ostream& operator<<(ostream& os, double n)
  442. {
  443.     if (os.opfx()) {
  444.     // Uses __cvt_double (renamed from static cvt), in Chris Torek's
  445.     // stdio implementation.  The setup code uses the same logic
  446.     // as in __vsbprintf.C (also based on Torek's code).
  447.     char negative;
  448.     char buf[BUF];
  449.     int format_char;
  450.     int sign = '\0';
  451. #if 0
  452.     if (os.flags() ios::showpos) sign = '+';
  453. #endif
  454.     if (os.flags() & ios::fixed)
  455.         format_char = 'f';
  456.     else if (os.flags() & ios::scientific)
  457.         format_char = os.flags() & ios::uppercase ? 'E' : 'e';
  458.     else
  459.         format_char = os.flags() & ios::uppercase ? 'G' : 'g';
  460.  
  461.     int fpprec = 0; // 'Extra' (suppressed) floating precision.
  462.     int prec = os.precision();
  463.     if (prec < 0) prec = 6; // default.
  464.     else if (prec > MAXFRACT) {
  465.         if (os.flags() & (ios::fixed|ios::scientific) & ios::showpos)
  466.         fpprec = prec - MAXFRACT;
  467.         prec = MAXFRACT;
  468.     }
  469.  
  470.     // Do actual conversion.
  471.     char *cp = buf;
  472.     *cp = 0;
  473.     int size = __cvt_double(n, os.precision(),
  474.                 os.flags() & ios::showpoint ? 0x80 : 0,
  475.                 &negative,
  476.                 format_char, cp, buf + sizeof(buf));
  477.     if (negative) sign = '-';
  478.     if (*cp == 0)
  479.         cp++;
  480.  
  481.     // Calculate padding.
  482.     int fieldsize = size + fpprec;
  483.     if (sign) fieldsize++;
  484.     int padding = 0;
  485.     int w = os.width(0);
  486.     if (fieldsize < w)
  487.         padding = w - fieldsize;
  488.  
  489.     // Do actual output.
  490.     register streambuf* sbuf = os.rdbuf();
  491.     register i;
  492.     char fill_char = os.fill();
  493.     unsigned long pad_kind =
  494.         os.flags() & (ios::left|ios::right|ios::internal);
  495.     if (pad_kind != (unsigned long)ios::left // Default (right) adjust.
  496.         && pad_kind != (unsigned long)ios::internal)
  497.         for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  498.     if (sign)
  499.         sbuf->sputc(sign);
  500.     if (pad_kind == (unsigned long)ios::internal)
  501.         for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  502.     
  503.     // Emit the actual concented field, followed by extra zeros.
  504.     sbuf->sputn(cp, size);
  505.     for (i = fpprec; --i >= 0; ) sbuf->sputc('0');
  506.  
  507.     if (pad_kind == (unsigned long)ios::left) // Left adjustment
  508.         for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  509.     os.osfx();
  510.     }
  511.     return os;
  512. }
  513.  
  514. ostream& operator<<(ostream& stream, const char *s)
  515. {
  516.     if (stream.opfx()) {
  517.     size_t len = strlen(s);
  518.     int w = stream.width(0);
  519.     char fill_char = stream.fill();
  520.     register streambuf *sbuf = stream.rdbuf();
  521.     register int padding = w > len ? w - len : 0;
  522.     if (!(stream.flags() & ios::left)) // Default adjustment.
  523.         while (--padding >= 0) sbuf->sputc(fill_char);
  524.     sbuf->sputn(s, len);
  525.     if (stream.flags() & ios::left) // Left adjustment.
  526.         while (--padding >= 0) sbuf->sputc(fill_char);
  527.     stream.osfx();
  528.     }
  529.     return stream;
  530. }
  531.  
  532. ostream& operator<<(ostream& os, void *p)
  533. {
  534.     if (os.opfx()) {
  535.     os.form("%p", p);
  536.     os.osfx();
  537.     }
  538.     return os;
  539. }
  540.  
  541. ostream& operator<<(ostream& os, register streambuf* sbuf)
  542. {
  543.     if (os.opfx()) {
  544.     register streambuf* outbuf = os.rdbuf();
  545.     // FIXME: Should optimize!
  546.     for (;;) {
  547.         register int ch = sbuf->sbumpc();
  548.         if (ch == EOF) break;
  549.         if (outbuf->sputc(ch) == EOF) {
  550.         os.set(ios::badbit);
  551.         break;
  552.         }
  553.     }
  554.     os.osfx();
  555.     }
  556.     return os;
  557. }
  558.  
  559. ostream::ostream() : ios(¬_open_filebuf)
  560. {
  561.     _flags |= ios::dont_close;
  562.     _tie = NULL;
  563. }
  564.  
  565. ostream::ostream(streambuf* sb, ostream* tied) : ios(sb)
  566. {
  567.     _flags |= ios::dont_close;
  568.     _tie = tied;
  569. }
  570.  
  571. ostream::~ostream()
  572. {
  573.     if (!(_flags & (unsigned int)ios::dont_close))
  574.     delete _strbuf;
  575.     _flags |= ios::dont_close;
  576.     _strbuf = ¬_open_filebuf;
  577. }
  578.  
  579. ostream& ostream::seekp(streampos pos)
  580. {
  581.     pos = _strbuf->seekpos(pos, ios::out);
  582.     if (pos == streampos(EOF))
  583.     set(ios::badbit);
  584.     return *this;
  585. }
  586.  
  587. ostream& ostream::seekp(streamoff off, _seek_dir dir)
  588. {
  589.     streampos pos = _strbuf->seekoff(off, dir, ios::out);
  590.     if (pos == streampos(EOF))
  591.     set(ios::badbit);
  592.     return *this;
  593. }
  594.  
  595. streampos ostream::tellp()
  596. {
  597.     streampos pos = _strbuf->seekoff(0, ios::cur, ios::out);
  598.     if (pos == streampos(EOF))
  599.     set(ios::badbit);
  600.     return pos;
  601. }
  602.  
  603. ostream& ostream::form(const char *format ...)
  604. {
  605.     if (opfx()) {
  606.     va_list ap;
  607.     va_start(ap, format);
  608.     _strbuf->vform(format, ap);
  609.     va_end(ap);
  610.     }
  611.     return *this;
  612. }
  613.  
  614. ostream& ostream::vform(const char *format, _G_va_list args)
  615. {
  616.     if (opfx())
  617.     _strbuf->vform(format, args);
  618.     return *this;
  619. }
  620.  
  621. ostream& ostream::flush()
  622. {
  623.     if (_strbuf->sync())
  624.     set(ios::badbit);
  625.     return *this;
  626. }
  627.  
  628. ostream& flush(ostream& outs)
  629. {
  630.     outs.rdbuf()->overflow(EOF);
  631.     return outs;
  632. }
  633.  
  634. istream& ws(istream& ins)
  635. {
  636.     if (ins.ipfx1()) {
  637.     int ch = skip_ws(ins._strbuf);
  638.     if (ch == EOF)
  639.         ins.set(ios::eofbit);
  640.     else
  641.         ins._strbuf->sputbackc(ch);
  642.     }
  643.     return ins;
  644. }
  645.  
  646. // Skip white-space.  Return 0 on failure (EOF), or 1 on success.
  647. // Differs from ws() manipulator in that failbit is set on EOF.
  648. // Called by ipfx() and ipfx0() if needed.
  649.  
  650. int istream::_skip_ws()
  651. {
  652.     int ch = skip_ws(_strbuf);
  653.     if (ch == EOF) {
  654.     set(ios::eofbit|ios::failbit);
  655.     return 0;
  656.     }
  657.     else {
  658.     _strbuf->sputbackc(ch);
  659.     return 1;
  660.     }
  661. }
  662.  
  663. ostream& ends(ostream& outs)
  664. {
  665.     outs.put(0);
  666.     return outs;
  667. }
  668.  
  669. ostream& endl(ostream& outs)
  670. {
  671.     return flush(outs.put('\n'));
  672. }
  673.  
  674. ostream& ostream::write(const char *s, size_t n)
  675. {
  676.     if (opfx()) {
  677.     if (_strbuf->sputn(s, n) != n)
  678.         set(ios::failbit);
  679.     }
  680.     return *this;
  681. }
  682.  
  683. void ostream::do_osfx()
  684. {
  685.     if (flags() & ios::unitbuf)
  686.     flush();
  687.     if (flags() & ios::stdio) {
  688.     fflush(stdout);
  689.     fflush(stderr);
  690.     }
  691. }
  692.  
  693. const unsigned long ios::basefield = ios::hex|ios::oct|ios::dec;
  694. const unsigned long ios::floatfield = ios::scientific|ios::fixed;
  695. const unsigned long ios::adjustfield =
  696.     ios::left|ios::right|ios::internal;
  697.  
  698. iostream::iostream() : ios(¬_open_filebuf)
  699. {
  700.     _flags |= ios::dont_close;
  701.     _gcount = 0;
  702.     _tie = NULL;
  703. }
  704.  
  705. iostream::iostream(streambuf* sb, ostream* tied) : ios(sb)
  706. {
  707.     _flags |= ios::dont_close;
  708.     _tie = tied;
  709. }
  710.  
  711. iostream::~iostream()
  712. {
  713.     if (!(_flags & (unsigned int)ios::dont_close))
  714.     delete _strbuf;
  715.     _flags |= ios::dont_close;
  716.     _strbuf = ¬_open_filebuf;
  717. }
  718.  
  719. ostream& iostream::form(const char *format ...) // Copy of ostream::form.
  720. {
  721.     va_list ap;
  722.     va_start(ap, format);
  723.     _strbuf->vform(format, ap);
  724.     va_end(ap);
  725.     return *(ostream*)this;
  726. }
  727. istream& iostream::scan(const char *format ...) // Copy of istream::scan
  728. {
  729.     if (ipfx0()) {
  730.     va_list ap;
  731.     va_start(ap, format);
  732.     _strbuf->vscan(format, ap);
  733.     va_end(ap);
  734.     }
  735.     return *this;
  736. }
  737.  
  738. // NOTE: extension for compatibility with old libg++.
  739. // Not really compatible with fistream::close().
  740. #ifdef _STREAM_COMPAT
  741. void ios::close()
  742. {
  743.     if (!(_flags & (unsigned int)ios::dont_close))
  744.     delete _strbuf;
  745.     else if (_strbuf->_flags & _S_IS_FILEBUF)
  746.     ((struct filebuf*)_strbuf)->close();
  747.     else if (_strbuf != ¬_open_filebuf)
  748.     _strbuf->sync();
  749.     _flags |= ios::dont_close;
  750.     _strbuf = ¬_open_filebuf;
  751. }
  752.  
  753. int istream::skip(int i)
  754. {
  755.     int old = (_flags & ios::skipws) != 0;
  756.     if (i)
  757.     _flags |= ios::skipws;
  758.     else
  759.     _flags &= ~ios::skipws;
  760.     return old;
  761. }
  762. #endif
  763.